---
author: Marcus Rohrmoser
categories:
- en
- development
date: "2015-08-24T06:42:41+00:00"
tags:
- gdal
- gdal2tiles
- iOS
- Map
- MKTileOverlay
- Overlay
- Objective C
- Tile
title: MKTileOverlay with gdal2tiles or other TMS tiles
type: post
url: /2015/08/mktileoverlay-with-gdal2tiles-or-other-tms-tiles/
---
from iOS 7.0 onward there's the neat [MKTileOverlay::initWithURLTemplate:](https://developer.apple.com/library/prerelease/mac/documentation/MapKit/Reference/MKTileOverlay_class/#//apple_ref/occ/instm/MKTileOverlay/initWithURLTemplate:) for tiled overlay maps.

Sadly it can't display old-school [Tile Map Service][1] maps as e.g. produced by [gdal2tiles.py][2]<sup>1)</sup> because the y-values are flipped upside down. The [OSM Wiki][3] says about this fact: _&#8222;This is really just an unfortunate historical misalignment.&#8220;_

But with the drop-in [MKTileOverlay](https://developer.apple.com/library/prerelease/mac/documentation/MapKit/Reference/MKTileOverlay_class/) replacement below, you can use flipped geometries and add `{-y}` in the URL template to indicate such:

<!--more-->

<pre class="line-numbers"><code class="language-objc">#import <MapKit/MKTileOverlay.h>
// Copyright (c) 2015 Marcus Rohrmoser http://mro.name/me. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// interface unchanged
@interface MKTileOverlayOSMorTMS : MKTileOverlay
@end

/**
 * OSM: http://wiki.openstreetmap.org/w/index.php?title=Slippy_map_tilenames&oldid=1201902#X_and_Y
 * TSM: http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
 *
 * http://wiki.openstreetmap.org/w/index.php?title=Slippy_map_tilenames&oldid=1201902#Tile_numbers_to_lat..2Flon._.2F_Coordinates_to_tile_numbers_.2F_Sample_of_usage.2C_with_optional_tms-format_support
 * const MKTileOverlayPath p0 = { x : 70406, y : 42987, z:17 };
 * const MKTileOverlayPath p1 = convertYfromOSMtoTMS(p0);
 * assert(88084 == p1.y && "");
 */
static inline MKTileOverlayPath convertYfromOSMtoTMS(MKTileOverlayPath path)
{
  assert( (1 << path.z) == (NSInteger)pow(2, path.z) && "oops, pow failed" );
  path.y = (1 << path.z) - 1 - path.y;
  return path;
}

@implementation MKTileOverlayOSMorTMS

/** Detect `{-y}` in case and set `geometryFlipped` accordingly.
 */
-(instancetype)initWithURLTemplate:(NSString *)URLTemplate
{
  NSString *t = [URLTemplate stringByReplacingOccurrencesOfString:@"{-y}" withString:@"{y}"];
  if( self = [super initWithURLTemplate:t] ) {
    // NSParameterAssert(256.0f == self.tileSize.width);
    NSParameterAssert(256.0f == self.tileSize.height);
    NSParameterAssert(t.length == URLTemplate.length || t.length + 1 == URLTemplate.length);
    self.geometryFlipped = t.length < URLTemplate.length;
  }
  return self;
}

-(NSURL *)URLForTilePath:(MKTileOverlayPath)path
{
  if( self.geometryFlipped ) {
    // NSParameterAssert(256.0f == self.tileSize.width);
    NSParameterAssert(256.0f == self.tileSize.height);
    path = convertYfromOSMtoTMS(path);
  }
  MRLogD(@"%ld,%ld,%ld", (long)path.z, (long)path.x, (long)path.y, nil);
  return [super URLForTilePath:path];
}
@end
</code></pre>

<sup>1)</sup> see also the debian package [python-gdal][4] or the webpage of [Petr Přidal, the author of gdal2tiles][5] with a hint to it's [commercial successor][6].

 [1]: http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
 [2]: http://www.gdal.org/gdal2tiles.html
 [3]: http://wiki.openstreetmap.org/w/index.php?title=TMS&oldid=1112451#The_Y_coordinate_flipped
 [4]: https://packages.debian.org/de/wheezy/python-gdal
 [5]: http://www.klokan.cz/projects/gdal2tiles/
 [6]: http://www.maptiler.com/
